﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Input.Touch;


namespace G.XNA.Component
{
    /// <summary>
    /// 可以拖动的组件，默认组件内容是一个圆形的Texture2D材质
    /// </summary>
    public class Dragger : DrawableGameComponent, IProcessTouch
    {
        SpriteBatch spriteBatch;
        int? touchId;//辅助处理触控输入
        /// <summary>
        /// 位置改变
        /// </summary>
        public event EventHandler PositionChanged;

        public Dragger(Game game)
            : base(game)
        {
            // TODO: 在此处构造任何子组件
        }
        /// <summary>
        /// 默认为半透明圆型（半径=48像素）材质
        /// </summary>
        public Texture2D Texture { set; get; }
        /// <summary>
        /// Texture的对其点，通常设置为Texture中心
        /// </summary>
        public Vector2 Origin { set; get; }
        /// <summary>
        /// Texture的位置
        /// </summary>
        public Vector2 Position { set; get; }

        /// <summary>
        /// 允许游戏组件在开始运行之前执行其所需的任何初始化。
        /// 游戏组件能够在此时查询任何所需服务和加载内容。
        /// </summary>
        public override void Initialize()
        {
            // TODO: 在此处添加初始化代码

            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(this.GraphicsDevice);

            //创建默认的材质
            int radius = 48;
            Texture2D texture = new Texture2D(this.GraphicsDevice, 2 * radius, 2 * radius);
            uint[] pixels = new uint[texture.Width * texture.Height];

            for (int y = 0; y < texture.Height; y++)
                for (int x = 0; x < texture.Width; x++)
                {
                    Color clr = Color.Transparent;

                    if ((x - radius) * (x - radius) +
                        (y - radius) * (y - radius) <
                        radius * radius)
                    {
                        clr = new Color(0, 128, 128, 128);//半透明
                    }
                    pixels[y * texture.Width + x] = clr.PackedValue;
                }
            texture.SetData<uint>(pixels);

            Texture = texture;
            Origin = new Vector2(radius, radius);

            base.LoadContent();
        }

        /// <summary>
        /// 允许游戏组件进行自我更新。
        /// </summary>
        /// <param name="gameTime">提供计时值的快照。</param>
        public override void Update(GameTime gameTime)
        {
            // TODO: 在此处添加更新代码}
            base.Draw(gameTime);
        }

        public bool ProcessTouch(Microsoft.Xna.Framework.Input.Touch.TouchLocation touch)
        {
            if (Texture == null)
                return false;

            bool touchHandled = false;

            switch (touch.State)
            {
                case TouchLocationState.Pressed:
                    Rectangle rect = new Rectangle();
                    rect.X = (int)(Position.X - Origin.X);
                    rect.Y = (int)(Position.Y - Origin.Y);
                    rect.Width = Texture.Width;
                    rect.Height = Texture.Height;
                    if (rect.Contains((int)touch.Position.X, (int)touch.Position.Y))
                    {
                        touchId = touch.Id;
                        touchHandled = true;
                    }
                    break;

                case TouchLocationState.Moved:
                    if (touchId.HasValue && touchId.Value == touch.Id)
                    {
                        TouchLocation previousTouch;
                        touch.TryGetPreviousLocation(out previousTouch);
                        Position += touch.Position - previousTouch.Position;

                        // Fire the event!
                        if (PositionChanged != null)
                            PositionChanged(this, EventArgs.Empty);

                        touchHandled = true;
                    }
                    break;

                case TouchLocationState.Released:
                    if (touchId.HasValue && touchId.Value == touch.Id)
                    {
                        touchId = null;
                        touchHandled = true;
                    }
                    break;
            }
            return touchHandled;
        }

        public override void Draw(GameTime gameTime)
        {
            if (Texture != null)
            {
                spriteBatch.Begin();
                spriteBatch.Draw(Texture, Position, null, Color.White,
                                 0, Origin, 1, SpriteEffects.None, 0);
                spriteBatch.End();
            }
            base.Draw(gameTime);
        }
    }
}
